{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Dogs vs Cats 识别\n",
    "\n",
    "\n",
    "## 使用 Kaggle 的数据集\n",
    "\n",
    "**原始数据：**\n",
    "\n",
    " * 12500 dogs + 12500 cats 训练集\n",
    " \n",
    " * 12500 未标识测试集\n",
    " \n",
    "**转换：**\n",
    "\n",
    " * 1000 dogs + 1000 cats 训练集\n",
    " * 1000 dogs + 1000 cats 验证集\n",
    " * 500 dogs + 500 cats 测试集\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os, shutil\n",
    "\n",
    "# 创建相关的路径\n",
    "original_dataset_dir = '/Users/haoxingxiao/academic/data/dogs-vs-cats/train'\n",
    "base_dir = '/Users/haoxingxiao/academic/data/dogs-vs-cats/small'\n",
    "\n",
    "train_dir = os.path.join(base_dir, 'train')\n",
    "validation_dir = os.path.join(base_dir, 'validation')\n",
    "test_dir = os.path.join(base_dir, 'test')\n",
    "\n",
    "train_cats_dir = os.path.join(train_dir, 'cats')\n",
    "train_dogs_dir = os.path.join(train_dir, 'dogs')\n",
    "validation_cats_dir = os.path.join(validation_dir, 'cats')\n",
    "validation_dogs_dir  = os.path.join(validation_dir, 'dogs')\n",
    "test_cats_dir = os.path.join(test_dir, 'cats')\n",
    "test_dogs_dir = os.path.join(test_dir, 'dogs')\n",
    "\n",
    "# 猫测试集\n",
    "fnames = ['cat.{}.jpg'.format(i) for i in range(1000)]\n",
    "for fname in fnames:\n",
    "    src = os.path.join(original_dataset_dir, fname)\n",
    "    dst = os.path.join(train_cats_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "\n",
    "# 猫验证集\n",
    "fnames = ['cat.{}.jpg'.format(i) for i in range(1000, 1500)]\n",
    "for fname in fnames:\n",
    "    src = os.path.join(original_dataset_dir, fname)\n",
    "    dst = os.path.join(validation_cats_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "    \n",
    "# 猫测试集\n",
    "fnames = ['cat.{}.jpg'.format(i) for i in range(1500, 2000)]\n",
    "for fname in fnames:\n",
    "    src = os.path.join(original_dataset_dir, fname)\n",
    "    dst = os.path.join(test_cats_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "    \n",
    "# 狗测试集\n",
    "fnames = ['dog.{}.jpg'.format(i) for i in range(1000)]\n",
    "for fname in fnames:\n",
    "    src = os.path.join(original_dataset_dir, fname)\n",
    "    dst = os.path.join(train_dogs_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "\n",
    "# 狗验证集\n",
    "fnames = ['dog.{}.jpg'.format(i) for i in range(1000, 1500)]\n",
    "for fname in fnames:\n",
    "    src = os.path.join(original_dataset_dir, fname)\n",
    "    dst = os.path.join(validation_dogs_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n",
    "    \n",
    "# 狗测试集\n",
    "fnames = ['dog.{}.jpg'.format(i) for i in range(1500, 2000)]\n",
    "for fname in fnames:\n",
    "    src = os.path.join(original_dataset_dir, fname)\n",
    "    dst = os.path.join(test_dogs_dir, fname)\n",
    "    shutil.copyfile(src, dst)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total training cat images: 1000\n",
      "total training dog images: 1000\n",
      "total validation cat images: 500\n",
      "total validation dog images: 500\n",
      "total test cat images: 500\n",
      "total test dog images: 500\n"
     ]
    }
   ],
   "source": [
    "print('total training cat images:', len(os.listdir(train_cats_dir)))\n",
    "print('total training dog images:', len(os.listdir(train_dogs_dir)))\n",
    "print('total validation cat images:', len(os.listdir(validation_cats_dir)))\n",
    "print('total validation dog images:', len(os.listdir(validation_dogs_dir)))\n",
    "print('total test cat images:', len(os.listdir(test_cats_dir)))\n",
    "print('total test dog images:', len(os.listdir(test_dogs_dir)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "已经构建好了数据集。\n",
    "回忆MNIST数据集上的训练，这里复用：使用卷积层 Conv2D + relu 激活和 maxPooling2D 层交替。\n",
    "这里设定：输入 150*150， 输出到 Flatten 层是 7*7。\n",
    "\n",
    "**卷积神经网络模式的特点：深度不断增加，特征的尺寸逐渐减少**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "from keras import layers\n",
    "from keras import models\n",
    "\n",
    "model = models.Sequential()\n",
    "model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(150, 150, 3)))\n",
    "model.add(layers.MaxPooling2D((2, 2)))\n",
    "model.add(layers.Conv2D(64, (3, 3), activation='relu'))\n",
    "model.add(layers.MaxPooling2D((2, 2)))\n",
    "model.add(layers.Conv2D(128, (3, 3), activation='relu'))\n",
    "model.add(layers.MaxPooling2D((2, 2)))\n",
    "model.add(layers.Conv2D(128, (3, 3), activation='relu'))\n",
    "model.add(layers.MaxPooling2D((2, 2)))\n",
    "model.add(layers.Flatten())\n",
    "model.add(layers.Dense(512, activation='relu'))\n",
    "model.add(layers.Dense(1, activation='sigmoid'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "看一下模型的变化："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "conv2d_7 (Conv2D)            (None, 148, 148, 32)      896       \n",
      "_________________________________________________________________\n",
      "max_pooling2d_6 (MaxPooling2 (None, 74, 74, 32)        0         \n",
      "_________________________________________________________________\n",
      "conv2d_8 (Conv2D)            (None, 72, 72, 64)        18496     \n",
      "_________________________________________________________________\n",
      "max_pooling2d_7 (MaxPooling2 (None, 36, 36, 64)        0         \n",
      "_________________________________________________________________\n",
      "conv2d_9 (Conv2D)            (None, 34, 34, 128)       73856     \n",
      "_________________________________________________________________\n",
      "max_pooling2d_8 (MaxPooling2 (None, 17, 17, 128)       0         \n",
      "_________________________________________________________________\n",
      "conv2d_10 (Conv2D)           (None, 15, 15, 128)       147584    \n",
      "_________________________________________________________________\n",
      "max_pooling2d_9 (MaxPooling2 (None, 7, 7, 128)         0         \n",
      "_________________________________________________________________\n",
      "flatten_2 (Flatten)          (None, 6272)              0         \n",
      "_________________________________________________________________\n",
      "dense_3 (Dense)              (None, 512)               3211776   \n",
      "_________________________________________________________________\n",
      "dense_4 (Dense)              (None, 1)                 513       \n",
      "=================================================================\n",
      "Total params: 3,453,121\n",
      "Trainable params: 3,453,121\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "model.summary()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "配置网络用于训练："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "from keras import optimizers\n",
    "\n",
    "model.compile(loss='binary_crossentropy',\n",
    "             optimizer=optimizers.RMSprop(lr=1e-4),\n",
    "             metrics=['acc'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 图像预处理\n",
    "\n",
    "需要将150*150的图像转换成\\[0, 0\\]区间内的张量。Keras有对应的图像处理库。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found 2000 images belonging to 2 classes.\n",
      "Found 1000 images belonging to 2 classes.\n"
     ]
    }
   ],
   "source": [
    "from keras.preprocessing.image import ImageDataGenerator\n",
    "\n",
    "train_datagen = ImageDataGenerator(rescale = 1./255)\n",
    "test_datagen = ImageDataGenerator(rescale=1./255)\n",
    "\n",
    "train_generator = train_datagen.flow_from_directory(\n",
    "    train_dir,\n",
    "    target_size=(150, 150),\n",
    "    batch_size=20,\n",
    "    class_mode='binary')\n",
    "\n",
    "validation_generator = test_datagen.flow_from_directory(\n",
    "    validation_dir,\n",
    "    target_size=(150, 150),\n",
    "    batch_size=20,\n",
    "    class_mode='binary')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 这里获得的是生成器结果，Keras提供了对这种输入类型的支持。每次会输出20个样本，因此需要提供batch_number作为终止输入的时刻。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "_________________________________________________________________\n",
      "Layer (type)                 Output Shape              Param #   \n",
      "=================================================================\n",
      "conv2d_7 (Conv2D)            (None, 148, 148, 32)      896       \n",
      "_________________________________________________________________\n",
      "max_pooling2d_6 (MaxPooling2 (None, 74, 74, 32)        0         \n",
      "_________________________________________________________________\n",
      "conv2d_8 (Conv2D)            (None, 72, 72, 64)        18496     \n",
      "_________________________________________________________________\n",
      "max_pooling2d_7 (MaxPooling2 (None, 36, 36, 64)        0         \n",
      "_________________________________________________________________\n",
      "conv2d_9 (Conv2D)            (None, 34, 34, 128)       73856     \n",
      "_________________________________________________________________\n",
      "max_pooling2d_8 (MaxPooling2 (None, 17, 17, 128)       0         \n",
      "_________________________________________________________________\n",
      "conv2d_10 (Conv2D)           (None, 15, 15, 128)       147584    \n",
      "_________________________________________________________________\n",
      "max_pooling2d_9 (MaxPooling2 (None, 7, 7, 128)         0         \n",
      "_________________________________________________________________\n",
      "flatten_2 (Flatten)          (None, 6272)              0         \n",
      "_________________________________________________________________\n",
      "dense_3 (Dense)              (None, 512)               3211776   \n",
      "_________________________________________________________________\n",
      "dense_4 (Dense)              (None, 1)                 513       \n",
      "=================================================================\n",
      "Total params: 3,453,121\n",
      "Trainable params: 3,453,121\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n"
     ]
    }
   ],
   "source": [
    "model.summary()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/30\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:158: The name tf.get_default_session is deprecated. Please use tf.compat.v1.get_default_session instead.\n",
      "\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:163: The name tf.ConfigProto is deprecated. Please use tf.compat.v1.ConfigProto instead.\n",
      "\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:172: The name tf.global_variables is deprecated. Please use tf.compat.v1.global_variables instead.\n",
      "\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:180: The name tf.is_variable_initialized is deprecated. Please use tf.compat.v1.is_variable_initialized instead.\n",
      "\n",
      "WARNING:tensorflow:From /usr/local/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:187: The name tf.variables_initializer is deprecated. Please use tf.compat.v1.variables_initializer instead.\n",
      "\n",
      "100/100 [==============================] - 34s 340ms/step - loss: 0.6894 - acc: 0.5355 - val_loss: 0.6713 - val_acc: 0.5890\n",
      "Epoch 2/30\n",
      "100/100 [==============================] - 34s 338ms/step - loss: 0.6497 - acc: 0.6330 - val_loss: 0.6382 - val_acc: 0.6370\n",
      "Epoch 3/30\n",
      "100/100 [==============================] - 35s 347ms/step - loss: 0.6080 - acc: 0.6730 - val_loss: 0.6387 - val_acc: 0.6220\n",
      "Epoch 4/30\n",
      "100/100 [==============================] - 34s 338ms/step - loss: 0.5778 - acc: 0.6895 - val_loss: 0.5898 - val_acc: 0.6850\n",
      "Epoch 5/30\n",
      "100/100 [==============================] - 33s 331ms/step - loss: 0.5464 - acc: 0.7255 - val_loss: 0.5788 - val_acc: 0.7000\n",
      "Epoch 6/30\n",
      "100/100 [==============================] - 34s 340ms/step - loss: 0.5281 - acc: 0.7370 - val_loss: 0.5802 - val_acc: 0.6850\n",
      "Epoch 7/30\n",
      "100/100 [==============================] - 33s 326ms/step - loss: 0.4899 - acc: 0.7660 - val_loss: 0.5664 - val_acc: 0.6890\n",
      "Epoch 8/30\n",
      "100/100 [==============================] - 33s 331ms/step - loss: 0.4699 - acc: 0.7760 - val_loss: 0.5711 - val_acc: 0.7150\n",
      "Epoch 9/30\n",
      "100/100 [==============================] - 33s 333ms/step - loss: 0.4450 - acc: 0.7885 - val_loss: 0.5911 - val_acc: 0.6980\n",
      "Epoch 10/30\n",
      "100/100 [==============================] - 34s 338ms/step - loss: 0.4148 - acc: 0.8050 - val_loss: 0.5749 - val_acc: 0.7130\n",
      "Epoch 11/30\n",
      "100/100 [==============================] - 34s 340ms/step - loss: 0.3966 - acc: 0.8225 - val_loss: 0.5394 - val_acc: 0.7310\n",
      "Epoch 12/30\n",
      "100/100 [==============================] - 37s 374ms/step - loss: 0.3752 - acc: 0.8330 - val_loss: 0.6768 - val_acc: 0.6790\n",
      "Epoch 13/30\n",
      "100/100 [==============================] - 40s 405ms/step - loss: 0.3457 - acc: 0.8465 - val_loss: 0.5658 - val_acc: 0.7220\n",
      "Epoch 14/30\n",
      "100/100 [==============================] - 36s 359ms/step - loss: 0.3128 - acc: 0.8755 - val_loss: 0.5971 - val_acc: 0.7210\n",
      "Epoch 15/30\n",
      "100/100 [==============================] - 36s 359ms/step - loss: 0.3036 - acc: 0.8685 - val_loss: 0.5919 - val_acc: 0.7170\n",
      "Epoch 16/30\n",
      "100/100 [==============================] - 37s 366ms/step - loss: 0.2732 - acc: 0.8930 - val_loss: 0.6417 - val_acc: 0.7240\n",
      "Epoch 17/30\n",
      "100/100 [==============================] - 39s 388ms/step - loss: 0.2532 - acc: 0.9020 - val_loss: 0.6075 - val_acc: 0.7370\n",
      "Epoch 18/30\n",
      "100/100 [==============================] - 37s 372ms/step - loss: 0.2323 - acc: 0.9055 - val_loss: 0.7450 - val_acc: 0.6920\n",
      "Epoch 19/30\n",
      "100/100 [==============================] - 41s 407ms/step - loss: 0.2097 - acc: 0.9230 - val_loss: 0.6279 - val_acc: 0.7290\n",
      "Epoch 20/30\n",
      "100/100 [==============================] - 36s 357ms/step - loss: 0.1934 - acc: 0.9265 - val_loss: 0.7026 - val_acc: 0.7150\n",
      "Epoch 21/30\n",
      "100/100 [==============================] - 38s 380ms/step - loss: 0.1779 - acc: 0.9375 - val_loss: 0.6939 - val_acc: 0.7230\n",
      "Epoch 22/30\n",
      "100/100 [==============================] - 44s 436ms/step - loss: 0.1552 - acc: 0.9455 - val_loss: 0.7197 - val_acc: 0.7360\n",
      "Epoch 23/30\n",
      "100/100 [==============================] - 40s 404ms/step - loss: 0.1331 - acc: 0.9570 - val_loss: 0.8307 - val_acc: 0.7150\n",
      "Epoch 24/30\n",
      "100/100 [==============================] - 38s 381ms/step - loss: 0.1195 - acc: 0.9605 - val_loss: 0.7911 - val_acc: 0.7220\n",
      "Epoch 25/30\n",
      "100/100 [==============================] - 38s 380ms/step - loss: 0.1098 - acc: 0.9625 - val_loss: 0.9118 - val_acc: 0.6940\n",
      "Epoch 26/30\n",
      "100/100 [==============================] - 40s 397ms/step - loss: 0.0882 - acc: 0.9775 - val_loss: 0.9146 - val_acc: 0.7170\n",
      "Epoch 27/30\n",
      "100/100 [==============================] - 37s 367ms/step - loss: 0.0782 - acc: 0.9785 - val_loss: 0.8452 - val_acc: 0.7310\n",
      "Epoch 28/30\n",
      "100/100 [==============================] - 40s 398ms/step - loss: 0.0667 - acc: 0.9785 - val_loss: 0.9001 - val_acc: 0.7310\n",
      "Epoch 29/30\n",
      "100/100 [==============================] - 45s 448ms/step - loss: 0.0555 - acc: 0.9865 - val_loss: 1.0222 - val_acc: 0.7170\n",
      "Epoch 30/30\n",
      "100/100 [==============================] - 40s 402ms/step - loss: 0.0496 - acc: 0.9880 - val_loss: 0.9919 - val_acc: 0.7330\n"
     ]
    }
   ],
   "source": [
    "history = model.fit_generator(\n",
    "train_generator,\n",
    "steps_per_epoch=100,\n",
    "epochs=30,\n",
    "validation_data=validation_generator,\n",
    "validation_steps=50)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**记得保存模型哦**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.save('cats_and_dogs_small_1.h5')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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L9CkiR0uk/xyclyD5fr1rlrk0UcPLvlGcgdm2bSELz3XA8sQCapt27bMnz8/3mEYE1XhJur6uE3ej5K2Dt0YkzjCvQMzFl0MTQVL6MaYOonkDsxIuhgGE6tuyX5hCd0YUyeRDFAViy6GpoIldGNMnURSPRKLLoamgiX0AAMGDDjoJqGJEycyevToaj/XqlUrwN2lOXz48KDLnH322eTlVT+y8MSJEykOKOpccMEF/PDDD+GEHpY+ffqUDydgTLREUj0SaV/wWN4m70eW0AOMHDmSadOmVZo2bdo0Ro4cGdbnjznmGN54441ab79qQp81axZt27at9foCLV++nAMHDjB37lyKioqisk7jf+E0dkZaPWKJOnYsoQcYPnw47733XvnDLPLz89m4cSNnnHFGeb/wzMxMevXqxcyZMw/6fH5+Pj179gRgz549jBgxgu7duzNs2DD27NlTvtzo0aPLh94dP348AM888wwbN25kwIABDBgwAIC0tDS2b98OwJNPPknPnj3p2bNn+dC7+fn5dO/enRtvvJEePXowaNCgStsJlJuby1VXXcWgQYMqxb5q1SoGDhxIRkYGmZmZrF69GoDHH3+cXr16kZGRwbhx4+r0vZrkFG5jp1WPJJBQdxzF+lXTnaK336561lnRfd1+e813YV144YU6Y8YMVXVD2JYNNVtSUqI7d+5UVdVt27bpcccdp6Wlpaqq2rJlS1V1Q9n26NFDVVWfeOIJve6661RVddGiRdq4cePy4XfLhrLdv3+/nnXWWbpo0SJVVU1NTdVt27aVx1L2Pi8vT3v27Km7d+/WXbt2aXp6un711Ve6du1abdy4cfmwupdeeqm+8sorQffrhBNO0HXr1uns2bP15z//efn0fv366VtvvaWqqnv27NGioiKdNWuWnnrqqVpUVFQp3kB2p6j/xXqIalM7+HH43FgJrHYJrG5RVe6991569+7NwIED2bBhA1u2bAm5njlz5nDllVcClD9Mosz06dPJzMzk5JNPZunSpUEH3gr0ySefMGzYMFq2bEmrVq24+OKLy8dg6dq1K3369AFCD9Gbl5dH+/bt6dKlC+eccw4LFixgx44d7Nq1iw0bNpSPB9OiRQtSUlJ4//33ue6660jxrqPLht41/hBun3HrC558EvZOUa9Wod4NHTqUO+64g6+++ori4mL69u0LQE5ODtu2bWP+/Pk0bdqUtLS0oEPm1mTt2rVMmDCBefPmcdhhh3HttdfWaj1lyobeBTf8brAql9zcXL755hvS0tIAN1rkm2++aQ2kDVAkt9TX9xDVpu6shF5Fq1atGDBgANdff32lxtCdO3dyxBFH0LRp00rD0oZy5pln8tprrwGwZMkSvv76a8Al05YtW9KmTRu2bNnC3//+9/LPtG7dml27dh20rjPOOIMZM2ZQXFxMUVERb7/9NmeccUZY+1NaWsr06dNZvHhx+RC7M2fOJDc3l9atW9OpU6fyx9Dt3buX4uJizj33XF588cXyBtqyoXdN8oukz7j1BU8+ltCDGDlyJIsWLaqU0LOzs8nLy6NXr15MnTqVk046qdp1jB49mt27d9O9e3ceeOCB8pJ+RkYGJ598MieddBJXXHFFpaF3R40axeDBg8sbRctkZmZy7bXX0q9fP0455RRuuOEGTj755LD2Ze7cuXTs2JFjjjmmfNqZZ57JsmXL2LRpE6+88grPPPMMvXv35rTTTmPz5s0MHjyYIUOGkJWVRZ8+fZgwYUJY2zKJL5JqFGvsTD7i6tjrX1ZWllbtl718+XK6d+8el3hMZOxYJae0tODVKKmprguhSXwiMl9Vs4LNsxK6MT4Riz7jJrlYQjfGB6zPuIEETOjxqgIy4bNjVH+iPSwt2J2afpZQCb1FixYUFhZawkhgqkphYSEtWrSIdyi+F4thaY2/JVSjaElJCQUFBXXql21ir0WLFnTq1ImmTZvGOxRfi6QB0xo7G47qGkUT6saipk2b0rVr13iHYUxCiHRY2sAbhsAaOxuihKpyMcZUiNWwtMa/LKEbk6BsWFoTKUvoxiQoK3WbSFlCNyYOwu2OaKVuE4mEahQ1piGIZMRDYyJhJXRjoiQWNwEZE4mwErqIDBaRFSKySkQOeh6ZiKSKyAci8rWIfCQinaIfqjGJy24CMomgxoQuIo2BScD5QDowUkTSqyw2AZiqqr2Bh4HHoh2oMYksklJ3JN0RjYlEOCX0fsAqVV2jqvuAacDQKsukA//2fv8wyHxjfC3Sm4BsxEMTC+Ek9I7AdwHvC7xpgRYBF3u/DwNai0i7qisSkVEikiciedu2batNvMbUu3Dqxu0mIJMIotUoehdwlogsAM4CNgAHqi6kqpNVNUtVszp06BClTRsTO+HWjdtNQCYRhJPQNwCdA9538qaVU9WNqnqxqp4M3OdN+yFqURoTJ+HWjVup2ySCGkdbFJEmwErgHFwinwdcoapLA5ZpD+xQ1VIReRQ4oKoPVLfeYKMtGpNoGjVyJfOqRFzp2pj6VqdH0KnqfuBWYDawHJiuqktF5GERGeItdjawQkRWAkcC1rxjfMF6pJhkEtadoqo6C5hVZdoDAb+/AbwR3dCMiT8bltYkE7tT1JhqWN24SSaW0I2vhHv7fSSsR4pJFjY4l/ENG/TKNHRWQje+YYNemYbOErrxjUhuv49F1Ywx8WYJ3fhGuF0MIxkZ0ZhkYgnd+Ea4t99b1YzxK0voxjfC7WJo45Ebv7JeLsZXsrNr7tHSpYurZgk23ZhkZiV00+DYeOTGryyhmwbH7v40fmVVLqZBCqdqxphkYyV0Y4zxCUvoxhjjE5bQTcKzuzqNCY/VoZuEZgNuGRM+K6GbhGZ3dRoTPkvoJqHZXZ3GhM8Suklo9kxPY8JnCd0kNLur05jwWUI3cRNO7xW7q9OY8FkvFxMXkfResbs6jQmPldBNXFjvFWOizxK6iQvrvWJM9FlCN3FhvVeMiT5L6Caqwr1N33qvGBN9ltBN1ETy8GXrvWJM9ImqxmXDWVlZmpeXF5dtm9hISwv+aLfUVMjPr+9ojPEnEZmvqlnB5lkJ3USNNXQaE1+W0E3UWEOnMfFlCd1EjTV0GhNfltBN1FhDpzHxZQndhCXc7ojZ2a4BtLTU/bRkbkz9sbFcTI3sqUHGJIewSugiMlhEVojIKhEZF2R+FxH5UEQWiMjXInJB9EM18WLjrhiTHGpM6CLSGJgEnA+kAyNFJL3KYr8GpqvqycAI4I/RDtTEj3VHNCY5hFNC7wesUtU1qroPmAYMrbKMAod6v7cBNkYvRBNv1h3RmOQQTkLvCHwX8L7AmxboQeBKESkAZgG3BVuRiIwSkTwRydu2bVstwjXxYN0RjUkO0erlMhJ4SVU7ARcAr4jIQetW1cmqmqWqWR06dIjSpk2sWXdEY5JDOAl9A9A54H0nb1qgXwDTAVT1M6AF0D4aAZrYCbcrIlh3RGOSQTgJfR7QTUS6ikgzXKPnO1WWWQ+cAyAi3XEJ3epUElgkIyMaY5JDjQldVfcDtwKzgeW43ixLReRhERniLXYncKOILAJygWs1XsM4mrBYV0Rj/MeGz22gGjVyJfOqRFy1ijEmMdnwueYg1hXRGP+xhN5AWVdEY/zHEroPhdN7xboiGuM/NjiXz0QykFZ2tiVwY/zESug+Y71XjGm4LKH7jA2kZUzDZQk9SYR7V6f1XjGm4bKEngQiuavTeq8Y03BZQk8CkdSLW+8VYxouu1M0CdhdncaYMnanaJKzenFjTDgsoScBqxc3xoTDEnoSsHpxY0w47E7RJGF3dRpjamIldGOM8QlL6MYY4xOW0I0xxicsoRtjjE9YQjfGGJ+whB5n4Q66ZYwxNbFui3EUycMojDGmJlZCjyN7GIW/bN0Kt90GF18M+/fHO5ro2LcP/vpXt28m8VlCjyN7GIU/7N4NDz0Exx0HkybB22/DSy/FO6q6KS2FadOge3e47DI45RRYvjzeUfnDsmWxO+FbQo8jvw66tXcvbNwY7yhir6QE/vhHl8gffBDOO88lvZ/9zL3fsyfeEdbOBx9Av34wciS0bAnPPef25bTTYM6ceEdXd7t2wdy54b0+/dRdpURDSYk78WdkwLPPRmedB1HVuLz69u2rfvXqq6qpqaoi7uerr4ZeLiVF1Q2O614pKaGXTwZLl6r26OH2Y+PGeEcTG6Wlqn/9q2q3bu6YnXmm6mefVcz/6CM3/fHHo7O97dtV58xx242lBQtUzzvPxd65s+rLL6vu3+/mrV2retJJqs2aqb72WmzjiJUDB1T//GfVDh0q/8/V9OrWTfW99+q27QULVPv0ceu74gp3TGsLyNMQedUSepRFmqTDTf7J4OWX3b526KDaqJHquHHxjij6PvpItV8/d1x79FD929+CJ9rzz1dt21Z1x466be/AAdX+/d32Bg50J8xoW7tW9cor3d/gYYepTpigumfPwcvt2OFOXqD629/G/gQTTf/5j2rfvi72005TnTlT9f33a3699prqiSe6z11wgeqKFZFtd+9e1QcfVG3SRPXII1Xffrvu+2IJvR6lpgY/y6emxjuy2Nm9W/Xaa91+nn22K5lfeqlqmzaqO3fGO7roWLBA9cIL3T526qQ6ZUpF6TWYhQtdgqzrSW3SJLfNK690J4jGjVV/+cu6nyhUXSnxjjtcqbtFC9V77ql5vT/9pDpihIvppptUS0rqHkcsFRSoZme7eI85RjUnJ/IT0d697iTXurVq06aqY8eG93e9YIFqRobbdna2amFh7fahKkvo9UgkeEIXiXdksbF0qWp6utu/Bx6oSHJffun2e8KE6Gxn50532fvBB6qff666eLHq6tWqmzer7tpVfXKtjZ9+Up09W/X221WPP97tS9u2rhqluDi8dWRnqx5yiOqGDbWLYd061VatXMm8tFR12zbVm292Vz/t26u+8ELk+33ggOqnn7pEfuihbl3XX6+6fn1k6xg3rqLUumtXZDEUF6t+/HH432Nt7Nmj+pvfqLZsqdq8ueq990YeZ1WbN7vvClxp+8UX3XdR1d69quPHV5TKZ8yo23arsoRejxpSCf2ll1wVyxFHqP7rXwfPHzBAtWNH9wdeV5dfHvx7DXy1aKHarp1qly6uauDmm1WffdadBDZvrrlktn696vPPqw4ZUlFt1qKFS1qTJkVewlq92pXoRo2KfH9LS121TUqK6po1lectWFBR9XHyya5+vTqBSbxzZ/e5Zs1UL7nEnRhr6/nn3QkhM7Pm9pL8fPcdXnihO8mVnQyiXcIvLXUJ9Nhj3Tb+53/ccYimL79U/dnP3Pr79XMFjDKxKpUHsoRej/zY0FlVYBXLgAGh/5n/8Q+3zIsv1m17n33m1nPbbaoffuhK6tOnuxPKpEmqv/udq6ccO1b1lltUr7rK1ZO2aVP5OLRrp3rGGS7RP/OMS/Qff+xKm716VSyXlqY6ZozbTl1Lkbfe6qpJIq17feUVF8vTTwefX1qqOm1aRYIeMaJyKTswiXfqVJHEL7pIdepU1R9+qP0+BXr3XVcK7tKlcv3+vn2uvWHsWHcFV/bdHnusO4733uvejxkTvbr4ZctUzz3XrTc9PXghI1oOHHDf49FHu+1dfbXqr3/tSuVHHRX9UnkgS+j1LBEaOteujc0l7ZIlFVUs48dXf8lfWqrau7dbPtilaThKS1VPPdX9k0R6yVxa6qo7/vlP1YkTVW+8UfX0013VSWCib9LE1f3//vcuKUWzsW/zZpfwLr00ss8cfrjb75qqVIqKXFVXixau4HD//bFP4lXl5bnj06aN+w7L2k/AXaGcc47qE0+ofvNN5e/2rrvcMhMn1j2GGTPcvrZt606C+/bVfZ3h+PFHVyBo1kzL2zpiUSoPZAm9gZk1yyWpbt3c5WE0lJaq/uUv7nL5iCNcD4BwvPqq+yv7299qt93p093n//Sn2n0+mLJE/69/ud4OsUp0Ze6/3+3DvHnhLX/ZZS5BRNKjZe1aV4VSX0m8qvx81e7d3faPPlr1F79Qfeut6hsPDxxQHTbMFQ7qUqLNzXVXQaecorplS+3XUxerV9dc9RUtltAbkE8+cUm3Vy93Od6kieojj9St0fDbb13DXE1VLMHs2+euUvr3j3y7P/2k2rWr25doN3rWp507XSPmwIE1L/v22+57/r//q922VqyovyReVXHxwaXwmhQVqf7Xf7mri7y8yLf5l7+4E8KZZ7rSckNgCb2BWLTIXXJ26+ZKKjt2VDQm9u/vSnGR2LvXnQyaN3c9IiZNql1iffppF8N//hPZ5yZMcJ+bPTvybSaap55y+1Jdve7337vSbe/e9VdlkKWZlB8AAA61SURBVAg2bXJ18EcfHVlvm2efdd/poEHuxNBQWEJvAFatcvWYHTu6y98ypaXu0rt1a5eUw63PnzOn4hL60ktr3/VO1TWiHn6463EQrm3bXD3s4MG1324i2bPHJa2+fUO3J9xwg+s1UpuSarJbvNj9ffbqFV4f78cfd3+bQ4e6K7mGpM4JHRgMrABWAeOCzH8KWOi9VgI/1LROS+jRs3Gj6z1w+OGh613XrHENgqA6cqQrDQZTWOjqP8u6Wr77bnRifOABd2m8fHl4y992m0tuS5ZEZ/uJ4KWX3Pf6+usHz3v/fTfv7rvrP65EMXu2qwsfPDh0d8bSUve3VNazpyFdyZSpU0IHGgOrgWOBZsAiIL2a5W8DptS0Xkvo0bFjhyvVtGyp+sUX1S9bUuLqZhs3dqXFjz6qmFda6rrKdejg5o8d60rW0bJ1q+uJ8Ytf1LzsihWu7v+mm6K3/USwf78bLqBbt8qJaPdu11Zw/PGxvdkmGUye7LLS6NEH18WXlqreeaebf911yd2uUhd1TeinArMD3v8v8L/VLP8pcG5N6/VzQi8tdWNA3HSTu9svVoqKXH/rpk0j63P7+ecueZTdmr5kietaBq6nwMKFsYn3lltcD4yaqm+GDnV3SG7eHJs44mnmTPc9P/98xbQ77nDTPv44fnElkrFj3ffx5JMV0w4ccEkeXN/+2naD9YO6JvThwJ8D3l8F/CHEsqnAJqBxiPmjgDwgr0uXLvW1//Vq1SrXSFPWx7llS/eHGe074vbudXcSNmrkRv6L1K5dFVUr4Oov//jH2JZ6Vq928d5zT+hlykYqfPTR2MURT6Wlrurr6KPdCfmzz9yJdfToeEeWOA4ccF0wRVyvn5IS1WuuqaiSSqZBwWKhPhP6PcCzNa1TfVhC37vXJaEWLVwD5B/+4BLYBRdo+S3a4fZDrsmBA64eHNwlal28/barr66voW4vv9ydPIJ1rTtwwN1G3rmzv6se5s51x+7BB91NV506+WcQs2gpKnK31R9ySMWQvg89ZMlctR6rXIAFwGk1rVOTNKGHugN07tyK25uHD69cpVA2dvbRR7vS6S9/Wbd/3tJSd7s0qD72WF32Jj7y8lzsv/vdwfOmTnXzXnml/uOqb2UjN0L0Gp79ZvPmirGRojXImx/UNaE3AdYAXQMaRXsEWe4kIB+QmtapSZjQg43Rcsgh7kabcHqE/PCDS8QibhjPN9+sXWmjrIX/rruSt7RyzjnuOwjsblZU5EqqWVkNo37066/dCT47O96RJLb168O/K7mhiEa3xQu87oirgfu8aQ8DQwKWeRD4bTjr0yRM6KFGUYTIeoR88UXFaGwXXRS60bS0VPW779wAV08+6eq7TzlFy1v4kzWZq7qxVcDd5VfmkUe0wTUMrlzZMLvdmbqpLqGLm1//srKyNC8vLy7bro1GjVz6DibSr3D/fnj6aXjgARBxzxns2ROWLnUPkC37+eOPFZ/p0AHS0+Gss+D++6FJk9rvS7ypQmYm/PST29etW6FbNxg40D1g2RgTmojMV9WsYPOSOC3Ury5dYN26g6enpka+riZN4M47YfhwGDMG7rqrYl6HDtCjB1x5pfvZo4dL5B061D72RCMCd98NV1wB774L773nkvvjj8c7MmOSm5XQw5STA9dfX/kJ4CkpMHkyZGfXfr2q8MknUFrqv8Rdnf37Xam8WTNYtQpuvdVdtRhjqlddCb1RfQeTrLKz4dhjK6o6UlPrnszBlVbPOMNVpTSUZA4VVykrV8Khh7rqJ2NM3TT4hJ6TA2lpro48Lc29D2b1avjmG1ffrQr5+XVP5g3d9de7toPHH4d27eIdjTHJr0HXoefkwKhRUFzs3q9b597Dwcn6pZdc0r/66noN0ddSUmDx4nhHYYx/NOgS+n33VSTzMsXFbnqgAwfg5Zdh0CDo1Kn+4jPGmEg06IS+fn140z/4AL77zlURGGNMomrQCb1Ll/CmT5kChx8OQ4bEPiZjjKmtBp3QH33U1eMGSklx08vs2AEzZrg69ebN6zc+Y4yJRINO6NnZruthaqrrPhisK2JuLuzda9UtxpjEZzcW1aBvX3fTz4IF8Y7EGGPsxqJaW7QIvvrKSufGmORgCb0aL77obk2/4op4R2KMMTWzhB7Cvn3w6qswdKjdxWiMSQ6W0EP429+gsNCqW4wxycMSeghTpkDHjnDuufGOxBhjwmMJPYiNG+Ef/4BrroHGjeMdjTHGhMcSehBTp7quitddF+9IjDEmfJbQq1B11S1nnAHHHx/vaIwxJnyW0Kv49FP49ltrDDXGJB/fJvScHDfIlkj1D66oasoUaNXKPe/TGGOSiS8fcJGTAzfeCHv2uPfVPbgi0O7d8PrrcPnlLqkbY0wy8WUJ/b77KpJ5meJiGDeu+s+98QYUFVl1izEmOfkyoa9bF3x6QYHrwRJqPLIpU+CEE+C002IXmzHGxIovE/qhhwaf3ry561s+cKB72nygb7+FuXNdV0WR2MdojDHR5ruEXljoxmGpekNQSgr86U/w/PMwfz706gUPP+zGOgd7CLQxJvn5LqE/9ZRL0o88cvCDK666Cm66Cb75Bi65BMaPh4wM+Pe/3UOgBw+GY46J9x4YY0zt+OoBF4WFroviBRe43io1mT0bRo+GtWvd+zfecIneGGMSVXUPuPBVt8Unn3S9VO6/P7zlzzsPlixxpfkFC+Cii2IbnzHGxJJvEnphITzzDFx6KfTsGf7nUlLgN7+JXVzGGFNffFOHHmnp3Bhj/MYXCb22pXNjjPETXyT0stL5Aw/EOxJjjImfpE/o27e70vlll0GPHvGOxhhj4ifpE7rVnRtjjBNWQheRwSKyQkRWiUjQIa5E5DIRWSYiS0XkteiGGdz27fDss1Y6N8YYCKPboog0BiYB5wIFwDwReUdVlwUs0w34X+B0Vf1eRI6IVcCBrHRujDEVwimh9wNWqeoaVd0HTAOGVlnmRmCSqn4PoKpboxvmwax0bowxlYWT0DsC3wW8L/CmBToBOEFE/iMin4vI4GArEpFRIpInInnbtm2rXcQeK50bY0xl0WoUbQJ0A84GRgJ/EpG2VRdS1cmqmqWqWR06dKj1xqx0bowxBwsnoW8AOge87+RNC1QAvKOqJaq6FliJS/Ax8cQT1u/cGGOqCiehzwO6iUhXEWkGjADeqbLMDFzpHBFpj6uCWRPFOMuVlc4vvxzS02OxBWOMSU41JnRV3Q/cCswGlgPTVXWpiDwsIkO8xWYDhSKyDPgQGKuqhbEI+Omn3fNBre7cGGMqS7rx0HfuhPfft3HLjTENU3XjoSfdnaJt2lgyN8aYYJIuoRtjjAnOEroxxviEJXRjjPEJS+jGGOMTltCNMcYnLKEbY4xPWEI3xhifsIRujDE+YQndGGN8whK6Mcb4hCV0Y4zxCUvoxhjjE5bQjTHGJyyhG2OMT1hCN8YYn7CEbowxPmEJ3RhjfMISujHG+ERSJfScHEhLg0aN3M+cnHhHZIwxiaNJvAMIV04OjBoFxcXu/bp17j1Adnb84jLGmESRNCX0++6rSOZliovddGOMMUmU0Nevj2y6McY0NEmT0Lt0iWy6McY0NEmT0B99FFJSKk9LSXHTjTHGJFFCz86GyZMhNRVE3M/Jk61B1BhjyiRNLxdwydsSuDHGBJc0JXRjjDHVs4RujDE+YQndGGN8whK6Mcb4hCV0Y4zxCVHV+GxYZBuwrsrk9sD2OIQTK37bH/DfPvltf8B/++S3/YG67VOqqnYINiNuCT0YEclT1ax4xxEtftsf8N8++W1/wH/75Lf9gdjtk1W5GGOMT1hCN8YYn0i0hD453gFEmd/2B/y3T37bH/DfPvltfyBG+5RQdejGGGNqL9FK6MYYY2rJEroxxvhEQiR0ERksIitEZJWIjIt3PNEgIvkislhEFopIXrzjqQ0RmSIiW0VkScC0w0XkXyLyrffzsHjGGIkQ+/OgiGzwjtNCEbkgnjFGQkQ6i8iHIrJMRJaKyO3e9GQ+RqH2KSmPk4i0EJEvRWSRtz8PedO7isgXXs57XUSaRWV78a5DF5HGwErgXKAAmAeMVNVlcQ2sjkQkH8hS1aS9IUJEzgR2A1NVtac37XfADlX9rXfyPUxV74lnnOEKsT8PArtVdUI8Y6sNETkaOFpVvxKR1sB84H+Aa0neYxRqny4jCY+TiAjQUlV3i0hT4BPgduBXwFuqOk1EngcWqepzdd1eIpTQ+wGrVHWNqu4DpgFD4xyTAVR1DrCjyuShwMve7y/j/tmSQoj9SVqquklVv/J+3wUsBzqS3Mco1D4lJXV2e2+bei8F/ht4w5setWOUCAm9I/BdwPsCkvgABlDgnyIyX0RGxTuYKDpSVTd5v28GjoxnMFFyq4h87VXJJE31RCARSQNOBr7AJ8eoyj5Bkh4nEWksIguBrcC/gNXAD6q631skajkvERK6X/VX1UzgfGCMd7nvK+rq65K93+tzwHFAH2AT8ER8w4mciLQC3gT+n6r+GDgvWY9RkH1K2uOkqgdUtQ/QCVcjcVKstpUICX0D0DngfSdvWlJT1Q3ez63A27gD6QdbvHrOsvrOrXGOp05UdYv3D1cK/IkkO05eveybQI6qvuVNTupjFGyfkv04AajqD8CHwKlAWxEpewRo1HJeIiT0eUA3r9W3GTACeCfOMdWJiLT0GnQQkZbAIGBJ9Z9KGu8A13i/XwPMjGMsdVaW+DzDSKLj5DW4/QVYrqpPBsxK2mMUap+S9TiJSAcRaev9fgiu88dyXGIf7i0WtWMU914uAF4XpIlAY2CKqj4a55DqRESOxZXKwT2I+7Vk3CcRyQXOxg31uQUYD8wApgNdcMMfX6aqSdHQGGJ/zsZdxiuQD9wUUP+c0ESkPzAXWAyUepPvxdU5J+sxCrVPI0nC4yQivXGNno1xBejpqvqwlyOmAYcDC4ArVXVvnbeXCAndGGNM3SVClYsxxpgosIRujDE+YQndGGN8whK6Mcb4hCV0Y4zxCUvoxhjjE5bQjTHGJ/4/ixs1LTqSeMsAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "acc = history.history['acc']\n",
    "val_acc = history.history['val_acc']\n",
    "loss = history.history['loss']\n",
    "val_loss = history.history['val_loss']\n",
    "\n",
    "epochs = range(1, len(acc) + 1)\n",
    "\n",
    "plt.plot(epochs, acc, 'bo', label='Training Acc')\n",
    "plt.plot(epochs, val_acc, 'b', label='Validation Acc')\n",
    "plt.title('Training and Validation Accuracy')\n",
    "plt.legend()\n",
    "\n",
    "plt.figure()\n",
    "\n",
    "plt.plot(epochs, loss, 'bo', label='Training loss')\n",
    "plt.plot(epochs, val_loss, 'b', label='Validation loss')\n",
    "plt.title('Training and Validation Accuracy')\n",
    "plt.legend()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "可以看出，在5轮开始就已经到达稳定，超过10就开始过拟合。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
